#pragma once

// base types
template <typename T>
class BasePropertyGenerator
{
public:
	virtual ~BasePropertyGenerator(void) {}
	virtual T Gen( float fInterpAlpha ) const=0;
};

// derived types
// Random, Constant, Lerp
template <typename T>
class RandomGenerator : public BasePropertyGenerator<T>
{
public:
	RandomGenerator( const T& tMin, const T& tMax )
		: c_tMin( tMin ), c_tMax( tMax )
	{
		assert( c_tMin <= c_tMax );
	}
	virtual ~RandomGenerator() {}

	T Gen( float fInterpAlpha ) const {
		if ( fInterpAlpha <= 0 ) {
			return c_tMin;
		}
		else if ( fInterpAlpha >= 1 ) {
			return c_tMax;
		}
		return GetRandom();
	}

protected:
	virtual T GetRandom() const =0;

protected:
	const T c_tMin;
	const T c_tMax;
};

template <typename T>
class ConstantGenerator : public BasePropertyGenerator<T>
{
public:
	ConstantGenerator( const T t )
		: c_tConstant( t ) {}
	~ConstantGenerator() {}

	T Gen( float fInterpAlpha ) const {
		return c_tConstant;
	}

private:
	const T c_tConstant;
};

// specific types
// int, float, D3DXVECTOR3, D3DCOLOR

#define CreateGenerators( type, RandomFunction )					\
	class Random##type##Generator : public RandomGenerator<type>	\
	{																\
	public:															\
		Random##type##Generator( const type tMin, const type tMax )	\
			: RandomGenerator<type>( tMin, tMax ) {}				\
		~Random##type##Generator() {}								\
		type GetRandom() const RandomFunction						\
	};

CreateGenerators( int, { return (rand() % ( c_tMax - c_tMin + 1 )) + c_tMin; } );
CreateGenerators( FLOAT, { return ( c_tMax - c_tMin ) * randf() + c_tMin; } );
CreateGenerators( D3DXVECTOR3,\
{\
	D3DXVECTOR3 NewVector( c_tMax - c_tMin );\
	NewVector.x = NewVector.x * randf() + c_tMin.x;\
	NewVector.y = NewVector.y * randf() + c_tMin.y;\
	NewVector.z = NewVector.z * randf() + c_tMin.z;\
	return NewVector;\
})

BOOL operator<= ( D3DXCOLOR left, D3DXCOLOR right )
{
	return ( left.r <= right.r ) && ( left.g <= right.g ) && (left.b <= right.b );
}
CreateGenerators( D3DXCOLOR,\
{\
	D3DXCOLOR NewColor( c_tMax - c_tMin );\
	NewColor.r = NewColor.r * randf() + c_tMin.r;\
	NewColor.g = NewColor.g * randf() + c_tMin.g;\
	NewColor.b = NewColor.b * randf() + c_tMin.b;\
	NewColor.a = 1;\
	return NewColor;\
})